package com.yh.csx.event.store.mapstruct;

import com.yh.csx.bsf.core.util.JsonUtils;
import com.yh.csx.bsf.core.util.StringUtils;
import com.yh.csx.event.client.event.EventMessage;
import com.yh.csx.event.client.event.EventMessageBuilder;
import com.yh.csx.event.client.exception.EventErrorCode;
import com.yh.csx.event.client.exception.EventException;
import com.yh.csx.event.common.id.IdGenerator;
import com.yh.csx.event.common.utils.BeanUtils;
import com.yh.csx.event.store.gateway.event.dataobject.BizEventDo;
import lombok.Data;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.eventmesh.common.protocol.tcp.EventMeshMessage;
import org.apache.rocketmq.common.message.Message;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.Named;
import org.mapstruct.factory.Mappers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import static com.yh.csx.event.client.Constants.MSG_ID;
import static com.yh.csx.event.client.Constants.YYYY_MM_DD_HH_MM_SS;
import static com.yh.csx.event.client.event.EventMessageBuilder.APP_NAME;

/**
 * @author zhangsheng
 * @date 2021/7/30 15:50
 */

@Mapper(componentModel = "spring")
public interface EventMapStruct {
    Logger logger = LoggerFactory.getLogger(EventMapStruct.class);
    EventMapStruct INSTANCE = Mappers.getMapper(EventMapStruct.class);

    default EventMessage<String> convert2Message(BizEventDo eventDo) {
        EventMessage<String> eventMessage = EventMessageBuilder.<String>builder()
                .topic(eventDo.getTopic())
                .eventType(eventDo.getEventType())
                .bizId(eventDo.getBizId())
                .bizType(eventDo.getBizType())
                .creator(eventDo.getCreator())
                .orderId(eventDo.getOrderId())
                .locationCode(eventDo.getLocationCode())
                .payLoad(eventDo.getEventBody())
                .build();
        eventMessage.getHeads().put(APP_NAME, eventDo.getAppName());
        logger.info("=convert2Message=>rePush topic:{} , msgId:{} , msg:{}", eventDo.getTopic(), eventDo.getEventId(), eventMessage);
        return eventMessage;
    }

    @Mappings({@Mapping(source = "body", target = "body", qualifiedByName = "toHashMap")})
    EventMessageResp convert2Resp(EventMeshMessage msg);


    default BizEventDo convert(EventMeshMessage msg) {
        EventMessageResp resp = convert2Resp(msg);
        BizEventDo eventDo;
        try {
            eventDo = BeanUtils.map2Bean(resp.getBody(), BizEventDo.class);
            eventDo.setTopic(resp.getTopic());
            eventDo.setId(IdGenerator.uuid());
            eventDo.setEventBody(msg.getBody());
            eventDo.setEventId(resp.getProperties().get(MSG_ID));
            eventDo.setAppName(resp.getProperties().get(EventMessageBuilder.APP_NAME));
            eventDo.setEventType(resp.getProperties().get(EventMessageBuilder.EVENT_TYPE));
            eventDo.setLocationCode(resp.getProperties().get(EventMessageBuilder.LOCATION_CODE));
            eventDo.setBizId(StringUtils.isEmpty(resp.getProperties().get(EventMessageBuilder.BIZ_ID)) ? eventDo.getId() :
                    resp.getProperties().get(EventMessageBuilder.BIZ_ID));
            eventDo.setBizType(StringUtils.isEmpty(resp.getProperties().get(EventMessageBuilder.BIZ_TYPE)) ? eventDo.getEventType() :
                    resp.getProperties().get(EventMessageBuilder.BIZ_TYPE));
            eventDo.setCreator(StringUtils.isEmpty(resp.getProperties().get(EventMessageBuilder.CREATOR)) ? "sys" :
                    resp.getProperties().get(EventMessageBuilder.CREATOR));
            eventDo.setOrderId(StringUtils.isEmpty(resp.getProperties().get(EventMessageBuilder.ORDER_ID)) ? 0L :
                    Long.valueOf(resp.getProperties().get(EventMessageBuilder.ORDER_ID)));
            eventDo.setHappenTime(StringUtils.isEmpty(resp.getProperties().get(EventMessageBuilder.EVENT_CREATE_TIME)) ? new Date() :
                    DateUtils.parseDate(resp.getProperties().get(EventMessageBuilder.EVENT_CREATE_TIME), YYYY_MM_DD_HH_MM_SS));
        } catch (Exception e) {
            logger.warn("=convert=>convert to BizEventDo error:{}", resp, e);
            throw new EventException(EventErrorCode.MAP_CONVERT_BEAN_FAIL, EventMessageResp.class.getSimpleName());
        }

        return eventDo;
    }

    @Named("toHashMap")
    default Map<String, Object> toHashMap(String json) {
        return JsonUtils.<HashMap<String, Object>>deserialize(json, HashMap.class);
    }

    @Data
    class EventMessageResp {
        private String topic;
        private Map<String, String> properties;
        private Map<String, Object> body;
    }

    public static void main(String[] args) {
        Map<String, Object> map = new HashMap<>();
        map.put("id", "111111");
        try {
            BizEventDo eventDo = BeanUtils.map2Bean(map, BizEventDo.class);
            System.out.println(eventDo.getId());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
